<script>
export default {
  components: {},
  data () {
    return {
      radio: 0,
      activeName: '1',
    };
  },
  computed: {
    isButtonDisabled() {
      return this.radio === 0;
    }
  },
  methods: {
    check(radio) {
      console.log(radio)
      if (radio === 3) {
        this.$message.success('恭喜你，答对啦！')
      } else {
        this.$message.error('很遗憾，答错啦！')
      }
    },
  }
}
</script>

<template>
  <div>
    <div>
      <h1 align="center">3.6 基于模式的漏洞分析</h1>
      <el-divider></el-divider>
      <h3>基本原理</h3>
      基于模式的漏洞分析能够比较精确地通过形式化描述证明软件系统的执行，并能够以自动机的形式化语言对软件程序进行形式化建模，从
      <br>而合理地描述模式中各个模块的不同属性和属性之间的依赖关系，方便分析人员对软件系统的检测和分析。
      <br>在对软件程序进行模式分析之前，需要进行不同漏洞模式的构建，以待后续进行基于模式的匹配分析。根据不同漏洞模式触发原理和触发
      <br>机制，分析各个软件模块的不同属性和依赖关系，从中抽象出漏洞触发的核心条件，并建立基于形式化语言或描述性语言的漏洞模式。漏
      <br>洞模式建立后，下一步将针对二进制抽象进行基于漏洞模式的分析检测，首先将程序反汇编，并将反汇编代码转化为中间表示。针对二进
      <br>制程序的中间表示进一步分析出其相关属性信息描述，并针对其属性信息进行模式匹配和检测分析。
      <h3>方法实现</h3>
      <b>反汇编分析</b>
      <br>利用反汇编技术可以将二进制代码转化为可理解程度更高的汇编级代码。
      <ul>
        <li style="margin-left: 2em;">基本算法
          <ul>
            <li style="margin-left: 2em;">确定进行反汇编的代码区域，将指令和数据进行区分十分重要</li>
            <li style="margin-left: 2em;">确定指令的起始地址后，下一步就是读取该地址所包含的值，并执行一次表查找，将二进制操作码的置与它的汇编语言助记符对应起来</li>
            <li style="margin-left: 2em;">获取指令及其操作数后，需要对它的汇编语言等价形式进行转化，并将其在反汇编代码中输出</li>
            <li style="margin-left: 2em;">输出一条指令后，继续反汇编下一条指令，并重复上面的步骤，直到完成所有指令的反汇编</li>
          </ul>
        </li>
        <li style="margin-left: 2em;">线性扫描策略：该算法假设一条指令结束的地方就是另一条指令开始的地方，因此确定起始地址最为困难，其采用的方法是，假设程
          <br>序中标注为代码的节所包含的全部是机器语言指令。反汇编从代码段的第一个字节开始，以线性模式扫描整个代码段，逐条反汇编每
          <br>条指令，直到完成整个代码段。</li>
        <li style="margin-left: 2em;">基于控制流的递归扫描策略：为了避免把数据误认为指令，递归扫描算法重视控制流对反汇编过程的影响，控制流根据某一条指令是
          <br>否被另一条指令引用来决定是否对其进行反汇编。
        </li>
      </ul>
      将程序反汇编后，可以得到许多程序分析的重要信息：
      <ul>
        <li style="margin-left: 2em;">反汇编文本：包括汇编指令信息以及控制流信息等</li>
        <li style="margin-left: 2em;">函数信息：包括函数入口地址、长度、参数、导入导出表等</li>
        <li style="margin-left: 2em;">交叉引用：包括代码交叉引用和数据交叉引用</li>
      </ul>
      反汇编的不足：
      <ul>
        <li style="margin-left: 2em;">区分数据和代码十分困难</li>
        <li style="margin-left: 2em;">静态反汇编不能得到动态信息</li>
        <li style="margin-left: 2em;">指令长度是可变的，导致难以确定指令的结束位置</li>
      </ul>
      <h3>逆向中间表示</h3>
      <ul>
        <li style="margin-left: 2em;">逆向中间表示的设计原则：
          <ul>
            <li style="margin-left: 2em;">使用精简指令集，能够极大地减少汇编语言的指令数目，而且每条指令都采用标准字长，能够简化分析过程</li>
            <li style="margin-left: 2em;">使用足够多的寄存器数量，以保证中间语言能够满足不同处理器架构的需求</li>
            <li style="margin-left: 2em;">使用尽量简单的寻址方式：立即数寻址、寄存器寻址、直接寻址、寄存器间接寻址</li>
            <li style="margin-left: 2em;">使用统一的操作数格式，将隐式操作数转换为在中间语言指令中的显示操作数</li>
          </ul>
        </li>
      </ul>
      目前常用的中间表示有：REIL、VEX、Vine 等。
      <h3>漏洞模式建模和检测</h3>
      缓冲区溢出类漏洞模式：
      <ul>
        <li style="margin-left: 2em;">不安全函数调用模式。不安全函数主要包括一些没有判断输入长度的内存和字符串操作函数，如 strcpy，其原型是 <code>char *strcpy(char *dest, const char *src);</code>，<br>为其建立漏洞模式首先需要获取目标地址缓冲区大小和源数据缓冲区大小，如果源缓冲区大于目的缓冲区，则存在溢出。<ol>
          <li style="margin-left: 2em;">根据定义的不安全函数库，搜索定位程序中调用不安全函数的位置</li><li style="margin-left: 2em;">针对不同的不安全函数，定位源缓冲区和目的缓冲区，并通过回溯程序，确定源缓冲区和目的缓冲区的大小和位置关系以及源缓冲区数据是否可控</li>
          <li style="margin-left: 2em;">根据定义的基于不安全函数的缓冲区溢出模式，判断是否会发生缓冲区溢出漏洞</li></ol>
        </li>
        <li style="margin-left: 2em;"><p>循环写内存模式。如果一个程序的写缓冲区操作发生在循环中，且循环次数是用户可控的，就可能发生溢出，如：</p>
        <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-c"><span class="pln">taint_data </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">();</span></code></li><li class="L1"><code class="lang-c"><span class="pln">buffer</span><span class="pun">[</span><span class="lit">256</span><span class="pun">];</span></code></li><li class="L2"><code class="lang-c"><span class="pln">taint_size </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">taint_data</span><span class="pun">);</span></code></li><li class="L3"><code class="lang-c"><span class="pln">index </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L4"><code class="lang-c"><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">index </span><span class="pun">&lt;</span><span class="pln"> taint_size</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L5"><code class="lang-c"><span class="pln">    buffer</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> taint_data</span><span class="pun">[</span><span class="pln">index</span><span class="pun">];</span></code></li><li class="L6"><code class="lang-c"><span class="pln">    index</span><span class="pun">++;</span></code></li><li class="L7"><code class="lang-c"><span class="pun">}</span><span class="pln">   </span><span class="com">// 如果 taint_size &gt; buffer_size，则会发生溢出</span></code></li></ol></pre>
        <ol>
          <li>定位程序中的循环写内存操作的位置</li><li>通过回溯程序，做三方面的判断，即判断循环控制变量是否可控和程序对循环变量的验证是否完备、判断目的缓冲区是否位于关键的内存区域、判断源缓冲区的数据来源是否可控</li><li>根据回溯程序的结果，给出检测结果、即循环控制变量可控且验证不完备且目的缓冲区位于关键内存区域，即存在缓冲区溢出漏洞</li></ol>
        </li>
        <li style="margin-left: 2em;">循环写内存模式。如果一个程序的写缓冲区操作发生在循环中，且循环次数是用户可控的，就可能发生溢出，如：
          <ul>
            <li style="margin-left: 2em;"><pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-c"><span class="pln">taint_data </span><span class="pun">=</span><span class="pln"> fread</span><span class="pun">();</span></code></li><li class="L1"><code class="lang-c"><span class="pln">buffer</span><span class="pun">[</span><span class="lit">256</span><span class="pun">];</span></code></li><li class="L2"><code class="lang-c"><span class="pln">taint_size </span><span class="pun">=</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">taint_data</span><span class="pun">);</span></code></li><li class="L3"><code class="lang-c"><span class="pln">index </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L4"><code class="lang-c"><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">index </span><span class="pun">&lt;</span><span class="pln"> taint_size</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L5"><code class="lang-c"><span class="pln">    buffer</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> taint_data</span><span class="pun">[</span><span class="pln">index</span><span class="pun">];</span></code></li><li class="L6"><code class="lang-c"><span class="pln">    index</span><span class="pun">++;</span></code></li><li class="L7"><code class="lang-c"><span class="pun">}</span><span class="pln">   </span><span class="com">// 如果 taint_size &gt; buffer_size，则会发生溢出</span></code></li></ol></pre></li>
            <li style="margin-left: 2em;"><ol>
              <li style="margin-left: 2em;">定位程序中的循环写内存操作的位置</li><li style="margin-left: 2em;">通过回溯程序，做三方面的判断，即判断循环控制变量是否可控和程序对循环变量的验证是否完备、判断目的缓冲区是否位于关键的内存区域、判断源缓冲区的数据来源是否可控</li><li style="margin-left: 2em;">根据回溯程序的结果，给出检测结果、即循环控制变量可控且验证不完备且目的缓冲区位于关键内存区域，即存在缓冲区溢出漏洞</li></ol></li>
          </ul>
        </li>
      </ul>

      <el-divider></el-divider>

      <h3>基于模式的漏洞分析主要关注于：</h3>
      <el-radio-group v-model="radio">
        <el-radio :label="1">静态代码分析</el-radio>
        <el-radio :label="2">动态内存分析</el-radio>
        <el-radio :label="3">样本匹配和模式识别</el-radio>
        <el-radio :label="4">网络流量分析</el-radio>
        <el-button type="primary" plain :disabled="isButtonDisabled" @click="check(radio)">检查</el-button>
      </el-radio-group>
    </div>
    <el-divider></el-divider>

  </div>
</template>

<style scoped>

</style>